#include <sxSceneController.h>
#include <sxCanvas.h>
#include <sxColor4.h>

using Sx::Graphics::Color4f;

const unsigned int DEFAULT_BORDER_WIDTH = 2;
const Color4f DEFAULT_BORDER_COLOR = Color4f(0.4f);
const Color4f DEFAULT_BORDER_SELECTED_COLOR = Color4f(0.537255f, 0.705882f, 0.87451f, 1.0f);

Sx::Interface::SceneController::SceneController(Viewport* viewport, const std::shared_ptr<Canvas>& canvas, const std::shared_ptr<ScenePickingController>& pickingController, const std::shared_ptr<RendererImplementation>& cameraRenderer) : 
	ViewController(viewport, cameraRenderer) {

	this->pickingController = pickingController;
	this->canvas = canvas;
	this->borderWidth = DEFAULT_BORDER_WIDTH;
	this->borderColor = DEFAULT_BORDER_COLOR;
	this->borderColorSelected = DEFAULT_BORDER_SELECTED_COLOR;
}

Sx::Interface::SceneController::~SceneController() {}

bool Sx::Interface::SceneController::initialize() {
	return ViewController::initialize();
}

bool Sx::Interface::SceneController::preRender() const {
	bool success = ViewController::preRender();
	if ( this->pickingController != nullptr ) this->pickingController->update();
	else return false;

	if ( this->canvas == nullptr ) return false;

	

	return success;
}

void Sx::Interface::SceneController::render() const {
	ViewController::render();
	if ( this->borderWidth != 0 ) {
		if ( this->selected == true ) this->canvas->drawBorder(0, 0, 0, 0, this->borderWidth, this->borderColorSelected);
		else this->canvas->drawBorder(0, 0, 0, 0, this->borderWidth, this->borderColor);
	}
	this->canvas->render();
}

bool Sx::Interface::SceneController::postRender() const {
	return ViewController::postRender();
}

bool Sx::Interface::SceneController::project(const Eigen::Vector3f& worldPoint, Eigen::Vector2i& viewPoint) {
	if ( this->pickingController == nullptr ) {
		std::cerr << "[SceneController:project] Error: Picking controller has not been initialized (nullptr)." << std::endl;
		std::cerr << "  Provided viewPoint has not been modified." << std::endl;
		return false;
	}

	return this->pickingController->project(this->camera->getObject().get(), worldPoint, viewPoint);
}

bool Sx::Interface::SceneController::unproject(int x, int y, Eigen::Vector3f& origin, Eigen::Vector3f& direction) {
	if ( this->pickingController == nullptr ) {
		std::cerr << "[SceneController:unproject] Error: Picking controller has not been initialized (nullptr)." << std::endl;
		std::cerr << "  Provided origin and direction have not been modified." << std::endl;
		return false;
	}

	return this->pickingController->unproject(this->camera->getObject().get(), x, y, origin, direction);
}

bool Sx::Interface::SceneController::createPickRay(int x, int y, Eigen::Vector3f& start, Eigen::Vector3f& end) {
	if ( this->pickingController == nullptr ) {
		std::cerr << "[SceneController:createPickRay] Error: Picking controller has not been initialized (nullptr)." << std::endl;
		std::cerr << "  Provided picking-segment start and end have not been modified." << std::endl;
		return false;
	}

	return this->pickingController->createPickRay(this->camera->getObject().get(), x, y, start, end);
}
